/**
 * @Copyright ®2015 Sinosoft Co. Ltd. All rights reserved.<br/>
 * 项目名称 : 中科软支付平台
 * 创建日期 : 2016年12月30日
 * 修改历史 : 
 *     1. [2016年12月30日]创建文件 by liuyujia
 */
package com.sinosoft.sinopay.timer.task.web.quartz.controller;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinosoft.sinocloud.platform.base.SinoBaseController;
import com.sinosoft.sinocloud.platform.common.util.HttpClientUtil;
import com.sinosoft.sinocloud.platform.common.util.SecurityUtil;
import com.sinosoft.sinopay.api.common.dto.pay.PaymentInfoDetailDTO;
import com.sinosoft.sinopay.merchants.dto.MerchantSignInfo;
import com.sinosoft.sinopay.merchants.facade.MerchantInfoFacadeService;
import com.sinosoft.sinopay.paytrade.config.ENUM_PAY_STATUS;
import com.sinosoft.sinopay.paytrade.dto.PayTradeNotifyRecordDTO;
import com.sinosoft.sinopay.timer.task.biz.config.ENUM_NOTIFY_STATUS;
import com.sinosoft.sinopay.timer.task.biz.config.ENUM_PAY_RESULT;
import com.sinosoft.sinopay.timer.task.biz.config.ENUM_PAY_TYPE;
import com.sinosoft.sinopay.timer.task.biz.config.ENUM_REPORT_NOTIFYTYPE;
import com.sinosoft.sinopay.timer.task.biz.service.BatchNofityService;
import com.sinosoft.sinopay.timer.task.web.util.TimerSignUtil;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 【通知第三方商户支付结果定时任务】
 * @author liuyujia
 * @date 2016年12月30日 下午12:03:20 
 * @version V1.0
 */
public class NotifyMerchantPiJob{
	protected final Logger logger = LogManager.getLogger(super.getClass());
	@Autowired
	private BatchNofityService batchNofityService;
	@Autowired
	private MerchantInfoFacadeService merchantInfoFacadeService;
	
	public void timerNotifyInfo() throws Exception{
		logger.info("后台回调开始......");
		JSONObject notifyInfo = new JSONObject();
		//查询回调信息表中回调状态为空或失败的单子，并且发送次数不超过上限
		List<PayTradeNotifyRecordDTO> tPayTradeNotifyRecordDTO = batchNofityService.queryPayTradeNotifyRecord(ENUM_NOTIFY_STATUS.NOTIFY_FAIL.code());
		if(null == tPayTradeNotifyRecordDTO || tPayTradeNotifyRecordDTO.size()==0){
	          logger.info("没有查询到待发送回调信息的支付交易。");
	      }
		for(PayTradeNotifyRecordDTO payTradeNotify:tPayTradeNotifyRecordDTO){
			Integer notifyNum = payTradeNotify.getNotifyTimes();//已回调次数
			Integer limitNum = payTradeNotify.getLimitNotifyTimes();
			//判断回调次数是否达到上限
			if(notifyNum<limitNum){
				//根据回调信息表中的PayNo在主表中找到该支付订单的详情
				List<PaymentInfoDetailDTO> tPaymentInfoDetailDTO = batchNofityService.queryPayInfoByPayNo(payTradeNotify.getPayNo());
				logger.info("订单："+payTradeNotify.getPayNo()+"的支付结果编码为："+tPaymentInfoDetailDTO.get(0).getPayState());
				String resultCode = tPaymentInfoDetailDTO.get(0).getPayState();
				if(resultCode==null || "".equals(resultCode)){
					resultCode = ENUM_PAY_RESULT.PAY_EXEP.code();
					notifyInfo.put("resultCode", ENUM_PAY_RESULT.PAY_EXEP.code());
				}
				else if(resultCode.equals(ENUM_PAY_STATUS.PAY_PAYED.code())){
					resultCode = ENUM_PAY_RESULT.PAY_PAYSUCC.code();
					notifyInfo.put("resultCode", ENUM_PAY_RESULT.PAY_PAYSUCC.code());
				}
				else{
					resultCode = ENUM_PAY_RESULT.PAY_FAIL.code();
					notifyInfo.put("resultCode", ENUM_PAY_RESULT.PAY_FAIL.code());   
				}
				notifyInfo.put("merchantCode", tPaymentInfoDetailDTO.get(0).getMerchantCode());
				notifyInfo.put("bizNo", tPaymentInfoDetailDTO.get(0).getBizNo());
				notifyInfo.put("payNo", payTradeNotify.getPayNo());
				notifyInfo.put("payAmount", tPaymentInfoDetailDTO.get(0).getPayAmount());
				notifyInfo.put("payDate", tPaymentInfoDetailDTO.get(0).getPayDate());
				notifyInfo.put("bankCode", tPaymentInfoDetailDTO.get(0).getBankCode());
				notifyInfo.put("accountNo", tPaymentInfoDetailDTO.get(0).getAccountNo());
				notifyInfo.put("bankName", tPaymentInfoDetailDTO.get(0).getBankName());
				String resultMsg = null;
				if(tPaymentInfoDetailDTO.get(0).getReturnMsg()==null){
					notifyInfo.put("resultMsg", "");
				}
				else if(tPaymentInfoDetailDTO.get(0).getReturnMsg()!=null && 
						tPaymentInfoDetailDTO.get(0).getPayType().equals(ENUM_PAY_TYPE.GATEWAY.code())){
					if("0000".equals(tPaymentInfoDetailDTO.get(0).getReturnCode())){
						notifyInfo.put("resultMsg", "");
					}
					else{
						resultMsg = tPaymentInfoDetailDTO.get(0).getReturnMsg();
						notifyInfo.put("resultMsg", tPaymentInfoDetailDTO.get(0).getReturnMsg());
					}
				}
				else{
					resultMsg = tPaymentInfoDetailDTO.get(0).getReturnMsg();
					notifyInfo.put("resultMsg", tPaymentInfoDetailDTO.get(0).getReturnMsg());
				}
				//根据商户编码找到后台回调地址
				MerchantSignInfo tMerchantSignInfo = merchantInfoFacadeService.getMerchantByCode(tPaymentInfoDetailDTO.get(0).getMerchantCode());
				String signKey = null;
				String backUrl = null;
				if(tMerchantSignInfo!=null){
					signKey = tMerchantSignInfo.getSignKey();
					backUrl = tMerchantSignInfo.getPayBackNotifyURL();
				}else{
					logger.info("没有查询到商户信息。");
				}
				//支付参数加密
				String data = notifyInfo.toString();
				logger.info("后台回调信息为："+data);
				String encryptData = SecurityUtil.aesEncrypt(data, signKey);
				//签名
				Map<String,String> md5Data = new HashMap<String,String>();
				md5Data.put("merchantCode", tPaymentInfoDetailDTO.get(0).getMerchantCode());
				md5Data.put("bizNo", tPaymentInfoDetailDTO.get(0).getBizNo());
				md5Data.put("payNo", payTradeNotify.getPayNo());
				if(tPaymentInfoDetailDTO.get(0).getPayAmount()==null){
					throw new Exception("查询金额为null");
				}
				String money = transAmount(tPaymentInfoDetailDTO.get(0).getPayAmount());
				md5Data.put("payAmount", money);
				md5Data.put("resultCode", resultCode);
				md5Data.put("resultMsg", resultMsg);
				String tCompareSignMsg = TimerSignUtil.encryMD5(md5Data, signKey);
				
				Map<String,String> paramMap = new HashMap<String,String>();
	            paramMap.put("notify_data", encryptData);
	            paramMap.put("notify_sign", tCompareSignMsg);
	            //记录回调日志表
	            PayTradeNotifyRecordDTO cPayTradeNotifyRecordDTO = new PayTradeNotifyRecordDTO();
	            cPayTradeNotifyRecordDTO.setMerchantCode(tPaymentInfoDetailDTO.get(0).getMerchantCode());
	            cPayTradeNotifyRecordDTO.setPayNo(payTradeNotify.getPayNo());;
	            cPayTradeNotifyRecordDTO.setNotifyUrl(backUrl);
	            cPayTradeNotifyRecordDTO.setNotifyType(ENUM_REPORT_NOTIFYTYPE.BACK_NOTIFY.code());
	            cPayTradeNotifyRecordDTO.setNotifyTimes(notifyNum);
	            cPayTradeNotifyRecordDTO.setLimitNotifyTimes(limitNum);
	            cPayTradeNotifyRecordDTO.setCreateDate(new Date());
	            cPayTradeNotifyRecordDTO.setRequestContent(data);
	            PayTradeNotifyRecordDTO mPayTradeNotifyRecordDTO = new PayTradeNotifyRecordDTO();
	            mPayTradeNotifyRecordDTO.setPayNo(payTradeNotify.getPayNo());
	            //发送回调请求
	            try{
	            	//更新回调记录表
	            	mPayTradeNotifyRecordDTO.setRequestContent(payTradeNotify.getPayNo());
	            	mPayTradeNotifyRecordDTO.setNotifyTimes(notifyNum+1);
	            	logger.info("发送回调信息开始："+paramMap);
	            	JSONObject response = JSONObject.fromObject(HttpClientUtil.postData(backUrl, paramMap));
	            	String returnCode = response.getString("returnCode");
	            	cPayTradeNotifyRecordDTO.setResponseContent(response.toString());
	            	mPayTradeNotifyRecordDTO.setResponseContent(response.toString());
	            	logger.info("接收到商户回调返回结果:"+returnCode);
	            	if("00".equals(returnCode)){
	            		cPayTradeNotifyRecordDTO.setNotifyResult("SUCCESS");
		            	mPayTradeNotifyRecordDTO.setNotifyResult("SUCCESS");
	            		}
	            	else{
	            		cPayTradeNotifyRecordDTO.setNotifyResult("FAIL");
		            	mPayTradeNotifyRecordDTO.setNotifyResult("FAIL");
	            	}
	            }
	            catch(Exception te){
	            	logger.info("回调商户发生异常");
	    			te.printStackTrace();
	            	mPayTradeNotifyRecordDTO.setNotifyTimes(notifyNum+1);
	            	mPayTradeNotifyRecordDTO.setNotifyResult("ERROR");
	            }
	            finally{
	            	logger.info("=========新增回调日志start=========");
	            	batchNofityService.addPayTradeNotifyRecordLog(cPayTradeNotifyRecordDTO);
	            	logger.info("=========更新回调状态start=========");
	            	batchNofityService.modifyPayTradeNotifyRecord(mPayTradeNotifyRecordDTO);
	            }
			}
			else{
				logger.info("回调次数已达到上限。");
			}
		}
	}
	
	public String transAmount(BigDecimal tPayAmount){
        BigDecimal fen = tPayAmount.multiply(new BigDecimal("100"));
        long fenAmount = fen.intValue();
        String money = String.valueOf(fenAmount);
	return money;
	
}
}
